package org.softmed.rest.server.core.restlet;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.restlet.Application;
import org.restlet.Context;
import org.restlet.Restlet;
import org.restlet.Router;

public class RESTletServerApplication extends Application {

	private Router rootRouter;
	private Router mainRouter;

	Map<String, RouterSet> sets = new HashMap<String, RouterSet>();

	List<String> deployedURIs = new ArrayList<String>();
	Map<Router, String> routerURIS = new HashMap<Router, String>();

	public void setupResource(String setName, String uri,
			RESTConfiguredRestlet cr) {

		if (deployedURIs.contains(uri)) {
			System.err.println("Trying to deploy duplicated URI : " + uri
					+ " from app : " + cr.getTabulaApplication().getName()
					+ " mod: " + cr.getModule().getName());
			return;

		}

		deployedURIs.add(uri);

		RouterSet set = getSet(setName);
		Router router = new Router(getContext().createChildContext());
		rootRouter.attach(uri, router);
		routerURIS.put(router, uri);
		cr.setContext(getContext().createChildContext());
		router.attach(cr);
		set.getResources().add(router);
	}

	public RouterSet getSet(String setName) {
		RouterSet set = sets.get(setName);
		if (set == null) {
			set = new RouterSet();
			sets.put(setName, set);
		}
		return set;
	}

	// public void setupAdminResource(String uri, RESTConfiguredRestlet cr) {
	// Router router = new Router(getContext());
	// rootRouter.attach(uri, router);
	// router.attach(cr);
	// adminResources.add(router);
	// }

	public void removeAllResources() {
		Set<String> names = sets.keySet();
		for (String set : names) {
			removeAllResources(set);
		}
		deployedURIs.clear();
		routerURIS.clear();
	}

	public void removeAllResources(String setName) {
		RouterSet set = sets.get(setName);

		if (set == null)
			return;

		for (Router router : set.getResources()) {
			rootRouter.detach(router);
			deployedURIs.remove(routerURIS.get(router));
			routerURIS.remove(router);
		}
		set.getResources().clear();

		rootRouter.detach(mainRouter);
		mainRouter = new Router(getContext().createChildContext());
		rootRouter.attach(mainRouter);
	}

	// public void setupResource(String uri, RESTConfiguredRestlet cr) {
	// Router router = new Router(getContext());
	// mainRouter.attach(uri, router);
	// router.attach(cr);
	// installedResources.add(router);
	// }

	// public void removeAllResources() throws Throwable {
	// rootRouter.detach(mainRouter);
	// mainRouter = new Router(getContext());
	// rootRouter.attach(mainRouter);
	// // rootRouter.stop();
	// // for (Router router : installedResources) {
	// // router.stop();
	// // rootRouter.detach(router);
	// // }
	// installedResources.clear();
	// }

	public RESTletServerApplication(Context parentContext) {
		super(parentContext.createChildContext());
		parentContext.getAttributes().put("app", this);
		mainRouter = new Router(parentContext.createChildContext());
		rootRouter = new Router(parentContext.createChildContext());
		rootRouter.attach(mainRouter);
	}

	/**
	 * Creates a root Restlet that will receive all incoming calls.
	 */
	@Override
	public synchronized Restlet createRoot() {
		mainRouter.setContext(getContext().createChildContext());
		rootRouter.setContext(getContext().createChildContext());
		return rootRouter;
	}

	// public Router getRootRouter() {
	// return rootRouter;
	// }

}
